package com.fqgj.sentry.biz.decision;

import com.alibaba.fastjson.JSONObject;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.JSONUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.fqgj.sentry.api.domain.RiskApiResult;
import com.fqgj.sentry.api.domain.request.Column;
import com.fqgj.sentry.api.domain.request.DecisionVo;
import com.fqgj.sentry.biz.decision.data.DecisionResultAnalysis;
import com.fqgj.sentry.biz.store.DecisionDataSave;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.common.redis.RedisUtil;
import com.fqgj.sentry.exception.ErrorCodeEnums;
import com.fqgj.sentry.manage.entity.McApplicationEntity;
import com.fqgj.sentry.manage.entity.McMerchantEntity;
import com.fqgj.sentry.manage.service.ApplicationService;
import com.fqgj.sentry.policy.client.*;
import com.fqgj.sentry.policy.engine.domain.*;
import com.fqgj.sentry.policy.engine.domain.enums.*;
import com.fqgj.sentry.policy.engine.domain.enums.RuleTypeEnum;
import com.fqgj.sentry.policy.engine.resolver.Parser;
import com.fqgj.sentry.policy.entity.*;
import com.fqgj.sentry.policy.enums.*;
import com.fqgj.sentry.policy.enums.PolicyTypeEnum;
import com.google.gson.Gson;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by liupengpeng on 2017/8/10.
 */
@Service
public class DecisionBusiness {
    public static final Log LOGGER = LogFactory.getLog(DecisionBusiness.class);
    public static final Log decisionLogger = LogFactory.getLog("engine-decision-json");
    @Autowired
    private ApplicationService applicationService;
    @Autowired
    private EventService eventService;
    @Autowired
    private PolicySetService policySetService;
    @Autowired
    private ColumnService columnService;
    @Autowired
    private PolicyService policyService;
    @Autowired
    private RuleService ruleService;
    @Autowired
    private PolicyExecutorService executorService;
    @Autowired
    private ExecuteResultService executeResultService;
    @Autowired
    private RedisClient redisClient;

    @Autowired
    private DecisionDataSave decisionDataSave;
    @Autowired
    private DecisionResultAnalysis decisionResultAnalysis;

    @Autowired
    private FunctionService functionService;
    @Autowired
    private FunContextService funContextService;
    @Autowired
    private FunColumnService funColumnService;


    /**
     * 执行决策 结果
     */
    public RiskApiResult decisionResult(DecisionVo decisionVo) {
        Long startTime = System.currentTimeMillis();
        decisionLogger.info(new Gson().toJson(decisionVo));
        LOGGER.info("规则引擎调用开始,dealNo:{}", decisionVo.getFlowNo());

        List<Column> columns = decisionVo.getColumns();
        columns.add(new Column("sys_flow_no", decisionVo.getFlowNo()));
        columns.add(new Column("sys_merchant_code", decisionVo.getMerchantCode()));
        columns.add(new Column("sys_event_code", decisionVo.getEventCode()));
        columns.add(new Column("sys_app_code", decisionVo.getAppCode()));

        Gson gson = new Gson();
        String decisionVoStr = gson.toJson(decisionVo);
        //结果的封装  api result
        RiskApiResult riskResult = null;

        Long policySetId = null;
        try {
            List<PolicySet> resultList = new ArrayList<>();
            //1、参数 判断
            dataVerify(decisionVo);

            //  冠军者  挑战者 逻辑  2、json 获取
            PolicySet policySet = getPolicySet(false, decisionVo);
            policySetId = policySet.getPolicySetId();
            //3、调用 规则引擎
            Parser parser = new Parser();
            PcExecuteResultEntity executeResultEntity = executeResultService.selectExecuteResultListByResult(policySetId, ExecutorDefaultResultEnum.review);
            parser.setDefaultDecision(new Decision(Integer.valueOf(executeResultEntity.getId().toString()), executeResultEntity.getResult(), executeResultEntity.getLevel(), executeResultEntity.getResultType()));

            PolicySet result = parser.processPolicySet(policySet);

            resultList.add(result);


            //验证者逻辑
            try {
                PolicySet verifyPolicySet = getPolicySet(true, decisionVo);
                //3、调用 规则引擎
                if (verifyPolicySet != null) {
                    parser.setDefaultDecision(new Decision(Integer.valueOf(executeResultEntity.getId().toString()), executeResultEntity.getResult(), executeResultEntity.getLevel(), executeResultEntity.getResultType()));
                    PolicySet verifyResult = parser.processPolicySet(verifyPolicySet);
                    resultList.add(verifyResult);
                }
            } catch (Exception e) {
                LOGGER.error("规则引擎调用 异常(验证者)：e:{},flowNo:{}", e, decisionVo.getFlowNo());
            }
            //4、封装  api result
            riskResult = decisionResultAnalysis.getRiskResult(decisionVo.getMerchantCode(), decisionVo.getFlowNo(), resultList);
            LOGGER.info("本次决策结果为：{}", JSONObject.toJSONString(riskResult));
            //5、存储  风控流数据
            Long startSaveTime = System.currentTimeMillis();
//            decisionDataSave.saveData(decisionVo, riskResult, policySet);
            Long endSaveTime = System.currentTimeMillis();
            LOGGER.info("规则引擎调数据保存dealNo:{},耗时为：{}", decisionVo.getFlowNo(), endSaveTime - startSaveTime);
        } catch (BizException e) {
            riskResult = new RiskApiResult();
            riskResult.setFlowNo(decisionVo.getFlowNo());
            riskResult.setPolicySetId(policySetId);
            riskResult.setCode("1")
                    .setMsg(e.getMessage());
            LOGGER.error("flowNo:{},decisionVo:{},规则引擎调用业务异常：", decisionVo.getFlowNo(), decisionVoStr, e);
        } catch (Exception e) {
            riskResult = new RiskApiResult();
            riskResult.setFlowNo(decisionVo.getFlowNo());
            riskResult.setPolicySetId(policySetId);
            riskResult.setCode("1").setMsg("服务器异常,请稍候再试");
            LOGGER.error("flowNo:{},decisionVo:{},规则引擎调用非业务异常：", decisionVo.getFlowNo(), decisionVoStr, e);
        }
        Long endTime = System.currentTimeMillis();

        LOGGER.info("规则引擎调用 结束,dealNo:{},耗时为：{}", decisionVo.getFlowNo(), endTime - startTime);
        return riskResult;
    }

    private PolicySet getPolicySetFromCache(String key) {
        PolicySet policySet = null;
        try {
            policySet = redisClient.get(key);
        } catch (Exception e) {
            redisClient.del(key);
            LOGGER.error("redis get error!!", e);
        }
        return policySet;
    }


    /**
     * 数据校验
     *
     * @param decisionVo
     */
    private void dataVerify(DecisionVo decisionVo) {
        if (StringUtils.isEmpty(decisionVo.getMerchantCode())) {
            throw new BizException(ErrorCodeEnums.merchant_code_isnull_error);
        }
        if (StringUtils.isEmpty(decisionVo.getAppCode())) {
            throw new BizException(ErrorCodeEnums.app_code_isnull_error);
        }
        if (StringUtils.isEmpty(decisionVo.getEventCode())) {
            throw new BizException(ErrorCodeEnums.event_code_isnull_error);
        }
        if (StringUtils.isEmpty(decisionVo.getFlowNo())) {
            throw new BizException(ErrorCodeEnums.flowno_code_isnull_error);
        }
        if (CollectionUtils.isEmpty(decisionVo.getColumns())) {
            throw new BizException(ErrorCodeEnums.column_code_isnull_error);
        }
    }

    /**
     * 字段 校验
     *
     * @param policySetsId
     * @param executorId
     * @param columnList
     */
    private void columnListVerify(Long policySetsId, Long executorId, List<Column> columnList) {
        List<PcRuleEntity> ruleEntityList = ruleService.findActiveByPolicySetsIdAndExecutorId(policySetsId, executorId);
        if (CollectionUtils.isEmpty(ruleEntityList)) {
            throw new BizException(ErrorCodeEnums.rule_not_exist_error);
        }

        HashSet paramColumnList = new HashSet();
        for (Column column : columnList) {
            paramColumnList.add(column.getColumnCode());
        }

        List<Long> ruleIds = new ArrayList<>();
        HashSet policySetNeedColumn = new HashSet();
        for (PcRuleEntity ruleEntity : ruleEntityList) {
            ruleIds.add(ruleEntity.getId());
            List<PcRuleColumnEntity> ruleColumnEntityList = columnService.findRuleColumnByRuleId(ruleEntity.getId());
            if (CollectionUtils.isNotEmpty(ruleColumnEntityList)) {
                for (PcRuleColumnEntity ruleColumnEntity : ruleColumnEntityList) {
                    PcColumnEntity columnEntity = columnService.findById(ruleColumnEntity.getColumnId());
                    if (ColumnStatusEnum.isGrade(columnEntity.getStatus())) {
                        continue;
                    }
                    //判断规则关联字段  是否为函数
                    if (ColumnStatusEnum.isFun(columnEntity.getStatus())) {
                        //查询函数关联字段
                        addFunColumn(columnEntity.getId(), policySetNeedColumn);
                    } else {
                        policySetNeedColumn.add(ruleColumnEntity.getColumnCode());
                    }
                }
            }
        }
        if (!paramColumnList.containsAll(policySetNeedColumn)) {
            policySetNeedColumn.removeAll(paramColumnList);
            throw new BizException(ErrorCodeEnums.rule_column_not_exist_error, "入参字段不完整，请进行检测!需完善的字段为:" + new Gson().toJson(policySetNeedColumn));
        }
    }

    private void addFunColumn(Long functionId, HashSet policySetNeedColumn) {
        List<PcFunctionColumnEntity> functionColumnEntityList = funColumnService.findByFunctionId(functionId);
        for (PcFunctionColumnEntity functionColumnEntity : functionColumnEntityList) {
            if (functionColumnEntity.getRequired() == 1) {
                PcColumnEntity temp = columnService.findById(functionColumnEntity.getRelationColumnId());
                if (ColumnStatusEnum.isFun(temp.getStatus())) {
                    addFunColumn(temp.getId(), policySetNeedColumn);
                } else {
                    policySetNeedColumn.add(temp.getColumnCode());
                }
            }
        }
    }


    private PolicySet getPolicySet(Boolean verify, DecisionVo decisionVo) {
        //查询策略集
        McMerchantEntity merchantEntity = applicationService.selectMerchantByMerchantCode(decisionVo.getMerchantCode());
        if (merchantEntity == null) {
            LOGGER.error("商户不存在,code:{}", decisionVo.getMerchantCode());
            throw new BizException(ErrorCodeEnums.merchant_not_exists_error);
        }
        McApplicationEntity applicationEntity = applicationService.selectByMerchantIdAndAppCode(merchantEntity.getId(), decisionVo.getAppCode());
        if (applicationEntity == null) {
            throw new BizException(ErrorCodeEnums.application_not_exists_error);
        }
        PcEventEntity eventEntity = eventService.selectByMerchantIdAndCode(merchantEntity.getId(), decisionVo.getEventCode());
        if (eventEntity == null) {
            throw new BizException(ErrorCodeEnums.event_not_exists_error);
        }
        PcPolicySetsEntity policySetsEntity = policySetService.selectByAppIdAndEventId(applicationEntity.getId(), eventEntity.getId());
        if (policySetsEntity == null) {
            throw new BizException(ErrorCodeEnums.policy_set_not_exist_error);
        }
        List<Column> columnList = decisionVo.getColumns();
        if (CollectionUtils.isEmpty(columnList)) {
            throw new BizException(ErrorCodeEnums.column_not_exist_error);
        }


        //执行者
        PcExecutorEntity championExecutor = executorService.selectPcExecutorCurrent(policySetsEntity.getId(), ExecutorTypeEnum.champion.getType(), ActiveEnum.active.getType());
        PcExecutorEntity challengerExecutor = executorService.selectPcExecutorCurrent(policySetsEntity.getId(), ExecutorTypeEnum.challenger.getType(), ActiveEnum.active.getType());
        PcExecutorEntity verifierExecutor = executorService.selectPcExecutorCurrent(policySetsEntity.getId(), ExecutorTypeEnum.verifier.getType(), ActiveEnum.active.getType());

        Long executorId = null;
        String executorVersion = "";
        Integer executorType = null;

        if (!verify) {
            if (championExecutor == null && challengerExecutor == null) {
                throw new BizException(ErrorCodeEnums.executor_not_exist_error);
            }
            //筛选要执行则 执行者
            if (challengerExecutor == null && championExecutor != null) {
                executorId = championExecutor.getId();
                executorVersion = championExecutor.getVersion() + "";
                executorType = ExecutorTypeEnum.champion.getType();
            }
            if (challengerExecutor != null && championExecutor != null) {
                //查询 占比
                Integer executePercent = challengerExecutor.getExecutePercent();
                if (executePercent > 0) {
                    int randNum = new Random().nextInt(100) + 1;
                    if (randNum <= executePercent) {
                        executorId = challengerExecutor.getId();
                        executorVersion = challengerExecutor.getVersion() + "";
                        executorType = ExecutorTypeEnum.challenger.getType();
                    } else {
                        executorId = championExecutor.getId();
                        executorVersion = championExecutor.getVersion() + "";
                        executorType = ExecutorTypeEnum.champion.getType();
                    }
                } else {
                    executorId = championExecutor.getId();
                    executorVersion = championExecutor.getVersion() + "";
                    executorType = ExecutorTypeEnum.champion.getType();
                }
            }
            if (championExecutor == null && challengerExecutor != null) {
                Integer executePercent = challengerExecutor.getExecutePercent();
                if (executePercent != 100) {
                    throw new BizException(ErrorCodeEnums.executor_not_exist_error, "没有冠军者，并且挑战者占比设置异常");
                }
            }
        } else {
            if (verifierExecutor != null) {
                executorId = verifierExecutor.getId();
                executorVersion = verifierExecutor.getVersion() + "";
                executorType = ExecutorTypeEnum.verifier.getType();
            } else {
                return null;
            }
        }

        if (executorId == null) {
            throw new BizException(ErrorCodeEnums.executor_not_exist_error);
        }


        //根据 执行者 拿缓存json
        String key = RedisUtil.getKey(decisionVo.getMerchantCode(), decisionVo.getAppCode(), decisionVo.getEventCode(), executorId);
        PolicySet policySet = getPolicySetFromCache(key);
        if (policySet == null) {
            policySet = getPolicySet(decisionVo, executorId, executorType, policySetsEntity, merchantEntity, eventEntity);
            policySet.setMerchantId(merchantEntity.getId()).setAppId(applicationEntity.getId()).setVersion(executorVersion);

            LOGGER.info("executorId:{},policySet redis update", executorId);
            //放进去
            redisClient.set(key, policySet);

            //该执行者  字段是否完善
            columnListVerify(policySetsEntity.getId(), executorId, columnList);
        } else {
            VariableMap inputVarMap = getVarMap(merchantEntity.getId(),
                    decisionVo.getColumns());
            policySet.setInputVarMap(inputVarMap);
        }


        policySet.setFlowNo(decisionVo.getFlowNo());
        return policySet;
    }

    /**
     * 获取变量Map
     *
     * @param columnList
     * @return
     */
    public VariableMap getVarMap(Long merchantId, List<Column> columnList) {

        //入参  变量
        VariableMap inputVarMap = new VariableMap();
        Map<String, Variable> variableMap = new HashMap<>();
        for (Column column : columnList) {
            PcColumnEntity columnEntity = columnService.selectByMerchantAndCode(merchantId, column.getColumnCode());
            if (columnEntity == null) {
                Variable variable = new Variable();
                variable.setName(column.getColumnCode()).setValue(column.getColumnValue());

                variableMap.put(column.getColumnCode(), variable);
                continue;
//                throw new BizException(ErrorCodeEnums.policy_not_exist_error, "字段" + column.getColumnCode() + "有误，请检查");
            }

            OperationTypeEnum opType = transformOpType(columnEntity.getStatus());
            Variable var = new Variable(columnEntity.getId(),
                    columnEntity.getDisplayName(),
                    VariableTypeEnum.transformDatatype(columnEntity.getDataType()),
                    opType,
                    column.getColumnValue());
            if (opType.equals(OperationTypeEnum.SCRIPT)) {
                var.setScript(getScript(columnEntity.getId()));
            }
            variableMap.put(column.getColumnCode(), var);
        }
        inputVarMap.setVariableMap(variableMap);
        return inputVarMap;
    }

    /**
     * status 转换成 OperationType
     * status 1:系统字段(sys_)  2：自定义字段(loc_)  3:评分卡字段(grade_)  4:系统函数(sys_fun_)  5:自定义函数(fun_)
     * opType 1:值, 2:脚本
     *
     * @param status
     */
    public static OperationTypeEnum transformOpType(Integer status) {
        OperationTypeEnum opType;
        if (status.equals(4) || status.equals(5)) {
            opType = OperationTypeEnum.SCRIPT;
        } else {
            opType = OperationTypeEnum.VARIABLE;
        }
        return opType;
    }

    /**
     * 获取 执行者
     *
     * @param decisionVo
     * @return
     */
    private PolicySet getPolicySet(DecisionVo decisionVo, Long executorId, Integer executorType,
                                   PcPolicySetsEntity policySetsEntity, McMerchantEntity merchantEntity, PcEventEntity eventEntity) {
        PolicySet policySet = new PolicySet();

        policySet.setExecutorId(executorId).setEventId(eventEntity.getId())
                .setExecutorType(executorType)
                .setPolicySetId(policySetsEntity.getId());
        //填充最高的  执行者结果
        PcExecuteResultEntity executeResultEntity = executeResultService.selectMaxLevelExecuteResult(policySetsEntity.getId());
        policySet.setPolicyCompose(PolicyComposeEnum.transformByType(policySetsEntity.getMatchingType()))
                .setHighPriorityDecision(new Decision(executeResultEntity.getId().intValue(), executeResultEntity.getResult(), executeResultEntity.getLevel(), executeResultEntity.getResultType()));

        List<PcPolicyEntity> policyEntityList = policyService.selectByPolicySetIdAndExecutorId(policySetsEntity.getId(), executorId);
        if (CollectionUtils.isEmpty(policyEntityList)) {
            throw new BizException(ErrorCodeEnums.policy_not_exist_error);
        }

        Long merchantId = merchantEntity.getId();

        VariableMap inputVarMap = getVarMap(merchantId, decisionVo.getColumns());
        policySet.setInputVarMap(inputVarMap);

        List<Policy> policyList = new ArrayList<>();
        for (PcPolicyEntity policyEntity : policyEntityList) {
            List<PcRuleEntity> ruleEntityList = ruleService.findActiveRuleListByPolicyId(policyEntity.getId(), com.fqgj.sentry.policy.enums.RuleTypeEnum.custom.getType());
            if (CollectionUtils.isEmpty(ruleEntityList)) {
                continue;
            }
            Rule commonRule = null;
            PcRuleEntity entity = ruleService.findCommonRuleByPolicy(policyEntity.getId());
            if (entity != null) {
                String condition = ruleService.findRuleCondition(entity.getId());
                if (com.fqgj.common.utils.StringUtils.isNotEmpty(condition)) {
                    try {
                        commonRule = JSONUtils.json2pojo(condition, Rule.class);
                        commonRule.setRuleType(RuleTypeEnum.COMMON_RULE);
                        richRule(commonRule);
                    } catch (Exception e) {
                        throw new BizException(com.fqgj.sentry.common.exception.enums.ErrorCodeEnums.json_transform_error);
                    }
                }
            }

            Policy policy = new Policy();
            policy.setPolicyId(policyEntity.getId())
                    .setPolicyType(com.fqgj.sentry.policy.engine.domain.enums.PolicyTypeEnum.transformByType(policyEntity.getType()))
                    .setRuleCompose(RuleComposeEnum.transformByType(policyEntity.getMatchingType()))
                    .setPolicyName(policyEntity.getName())
                    .setCommonRule(commonRule);
            //如果是评分卡
            if (policyEntity.getType() == com.fqgj.sentry.policy.enums.PolicyTypeEnum.grade.getType()) {
                try {
                    //评分卡初始值 的设置
                    PcColumnEntity columnEntity = columnService.selectByMerchantAndCode(merchantEntity.getId(), policyEntity.getColumnCode());
                    policy.setInitalScoreVariable(new Variable(
                            columnEntity.getId(),
                            columnEntity.getColumnCode(),
                            VariableTypeEnum.transformDatatype(columnEntity.getDataType()),
                            OperationTypeEnum.VARIABLE,
                            Double.valueOf(policyEntity.getBaseScore().toString())
                    ));
                } catch (Exception e) {
                    throw new BizException(ErrorCodeEnums.json_transform_error, "评分卡字段查询异常");
                }
            }
            //规则组
            if (policyEntity.getType() == com.fqgj.sentry.policy.enums.PolicyTypeEnum.rules.getType()) {
                //如果是权重匹配
                if (policyEntity.getMatchingType() == PolicyMatchingTypeEnum.weight_match.getType()) {
                    try {
                        List<WeightRange> weightRange = JSONUtils.json2list(policyEntity.getWeightRange(), WeightRange.class);
                        if (CollectionUtils.isNotEmpty(weightRange)) {
                            for (WeightRange range : weightRange) {
                                Decision decision = range.getDecision();
                                if (decision != null) {
                                    PcExecuteResultEntity pcExecuteResultEntity = executeResultService.findByExecutorResultId(decision.getDecisionId().longValue());
                                    decision.setDecisionName(pcExecuteResultEntity.getResult())
                                            .setDecisionType(pcExecuteResultEntity.getResultType())
                                            .setPriority(pcExecuteResultEntity.getLevel());
                                }
                            }
                        }
                        policy.setWeightRange(weightRange);
                    } catch (Exception e) {
                        throw new BizException(ErrorCodeEnums.json_transform_error, "权重规则条件解析异常");
                    }
                }
            }

            Integer maxLevel = 0;
            Decision highPriorityDecision = new Decision();
            List<Rule> ruleList = new ArrayList<>();
            for (PcRuleEntity ruleEntity : ruleEntityList) {
                String ruleStr = ruleService.findRuleCondition(ruleEntity.getId());
                try {
                    Rule rule = JSONUtils.json2pojo(ruleStr, Rule.class);
                    //规则组
                    if (policyEntity.getType() == com.fqgj.sentry.policy.enums.PolicyTypeEnum.rules.getType()) {
                        //如果是首次匹配
                        if (policyEntity.getMatchingType() == PolicyMatchingTypeEnum.first_match.getType()) {
                            try {
                                if (RuleTypeEnum.COMMON_RULE == rule.getRuleType()) {
                                    continue;
                                }
                                Decision hitDecisionOption = rule.getHitDecisionOption();
                                PcExecuteResultEntity temp = executeResultService.findByExecutorResultId(hitDecisionOption.getDecisionId().longValue());
                                if (temp.getLevel() > maxLevel) {
                                    maxLevel = temp.getLevel();
                                    highPriorityDecision.setDecisionId(temp.getId().intValue()).setDecisionName(temp.getResult())
                                            .setDecisionType(temp.getResultType())
                                            .setPriority(temp.getLevel());
                                }
                            } catch (Exception e) {
                                throw new BizException(ErrorCodeEnums.json_transform_error, "首次匹配规则条件解析异常");
                            }
                        }
                    }

                    richRule(rule);
                    ruleList.add(rule);
                } catch (Exception e) {
                    LOGGER.error("规则配置异常:{}, {}", e, JSONObject.toJSONString(ruleStr));
                    throw new BizException(ErrorCodeEnums.json_transform_error, "规则配置异常");
                }
            }
            policy.setHighPriorityDecision(highPriorityDecision);
            policy.setRuleList(ruleList).setOrder(policyEntity.getSort());
            policyList.add(policy);
        }
        policySet.setPolicySet(policyList);
        return policySet;
    }

    /**
     * 根据字段id获取脚本
     *
     * @param columnId
     * @return
     */
    public Script getScript(Long columnId) {

        Script s = new Script();

        List<PcFunctionColumnEntity> params = functionService.selectParamsByColumnId(columnId);

        PcFunctionContextEntity pcFunctionContextEntity = functionService.selectScriptByColumnId(columnId);
        String script = pcFunctionContextEntity.getScriptDsl();

        s.setScript(script);

        Map<String, Variable> inputParams = new HashedMap();

        for (PcFunctionColumnEntity e : params) {
            String alias = e.getRelationColumnAlias();
            Long columnId1 = e.getRelationColumnId();
            PcColumnEntity column1 = columnService.selectColumn(columnId1);
            Variable var = transformPcColumnEntityToVariable(column1);
            inputParams.put(alias, var);
        }

        s.setInputParams(inputParams);

        return s;
    }

    /**
     * Column实体转化成Variable
     *
     * @param e
     * @return
     */
    public static Variable transformPcColumnEntityToVariable(PcColumnEntity e) {
        Variable v = new Variable();
        v.setId(e.getId());
        Integer status = e.getStatus();
        v.setOpType(transformOpType(status));
        v.setName(e.getColumnCode());
        v.setDisplayName(e.getDisplayName());
        v.setVarType(VariableTypeEnum.transformDatatype(e.getDataType()));
        return v;
    }

    /**
     * 丰富  规则内容
     *
     * @param rule
     * @return
     */
    private void richRule(Rule rule) {
        try {
            //丰富规则
            PcRuleEntity pcRuleEntity = ruleService.findById(rule.getRuleId());
            rule.setRuleName(pcRuleEntity.getName()).setOrder(pcRuleEntity.getSort()).setRuleType(RuleTypeEnum.transformByType(pcRuleEntity.getRuleType()));

            PcPolicyEntity policyEntity = policyService.findById(pcRuleEntity.getPolicyId());
            PolicyTypeEnum policyTypeEnum = PolicyTypeEnum.getEnumByType(policyEntity.getType());
            PolicyMatchingTypeEnum policyMatchingTypeEnum = PolicyMatchingTypeEnum.getEnumByType(policyEntity.getMatchingType());
            //丰富决策结果
            switch (policyTypeEnum) {
                //规则组
                case rules:
                    switch (policyMatchingTypeEnum) {
                        case first_match:
                        case bad_match:
                            if (RuleTypeEnum.COMMON_RULE == rule.getRuleType()) {
                                break;
                            }
                            Decision hitDecisionOption = rule.getHitDecisionOption();
                            PcExecuteResultEntity pcExecuteResultEntity = executeResultService.findByExecutorResultId(hitDecisionOption.getDecisionId().longValue());
                            hitDecisionOption.setDecisionName(pcExecuteResultEntity.getResult())
                                    .setDecisionType(pcExecuteResultEntity.getResultType())
                                    .setPriority(pcExecuteResultEntity.getLevel());
                            break;
                        case weight_match:
                            Weight weight = rule.getWeight();
                            weight.setVariable(richVariable(weight.getVariable()));
                            break;
                    }

            }
            //丰富执行条件的字段(函数)
            List<ConditionGroup> conditionGroups = rule.getConditionGroups();
            for (ConditionGroup conditionGroup : conditionGroups) {
                List<Condition> conditions = conditionGroup.getConditions();
                switch (policyTypeEnum) {
                    case grade:
                        ScoreCalculator scoreCalculator = conditionGroup.getScoreCalculator();
                        VariableOrConstant variable = scoreCalculator.getVariable();
                        if (variable != null && variable.getIsVar()) {
                            variable.setVariable(richVariable(variable.getVariable()));
                        }
                }
                for (Condition condition : conditions) {
                    condition.setFirstVariable(richVariable(condition.getFirstVariable()));
                    VariableOrConstant variable = condition.getSecondVariable();
                    if (variable != null) {
                        variable.setVariable(richVariable(variable.getVariable()));
                    }
                }
            }
        } catch (Exception e) {
            LOGGER.error("规则配置异常：{}", e);
            LOGGER.error("配置信息：{}", JSONObject.toJSONString(rule));
            throw new BizException("规则解析异常，请检查规则配置");
        }
    }


    /**
     * 丰富  变量对象
     *
     * @param variable
     * @return
     */
    private Variable richVariable(Variable variable) {
        if (variable == null) {
            return variable;
        }
        PcColumnEntity pcColumnEntity = columnService.findById(variable.getId());
        //变量属性
        variable.setName(pcColumnEntity.getColumnCode()).
                setDisplayName(pcColumnEntity.getDisplayName()).setRequired(true);
        if (pcColumnEntity.getDataType() != null) {
            variable.setVarType(VariableTypeEnum.transformDatatype(pcColumnEntity.getDataType()));
        }
        //函数
        if (ColumnStatusEnum.isFun(pcColumnEntity.getStatus())) {
            setScript(variable);
        } else {
            variable.setOpType(OperationTypeEnum.VARIABLE);
        }
        return variable;
    }


    private void setScript(Variable variable) {
        Script script = new Script();
        Map<String, Variable> inputParams = new HashMap<>();
        //查询关联字段
        List<PcFunctionColumnEntity> functionColumnList = funColumnService.findByFunctionId(variable.getId());
        for (PcFunctionColumnEntity functionColumnEntity : functionColumnList) {


            Variable temp = new Variable();
            PcColumnEntity funRelationColumn = columnService.findById(functionColumnEntity.getRelationColumnId());
            temp.setId(funRelationColumn.getId()).setName(funRelationColumn.getColumnCode()).setDisplayName(funRelationColumn.getDisplayName());
            if (funRelationColumn.getDataType() != null) {
                temp.setVarType(VariableTypeEnum.transformDatatype(funRelationColumn.getDataType()));
            } else {
                temp.setVarType(VariableTypeEnum.OBJECT);
            }
            if (ColumnStatusEnum.isFun(funRelationColumn.getStatus())) {
                setScript(temp);
            } else {
                temp.setOpType(OperationTypeEnum.VARIABLE);
            }
            temp.setRequired(functionColumnEntity.getRequired() == 1);


            inputParams.put(functionColumnEntity.getRelationColumnAlias(), temp);
        }
        PcFunctionContextEntity functionContextEntity = funContextService.findByFunctionId(variable.getId());
        script.setInputParams(inputParams).setScript(functionContextEntity.getScriptDsl());
        variable.setScript(script);
        //判断是否为 系统三方函数
        if (variable.getName().contains("sys_triple_fun")) {
            variable.setOpType(OperationTypeEnum.TRIPLE_SCRIPT);
        } else {
            variable.setOpType(OperationTypeEnum.SCRIPT);
        }
    }
}
